package torres.view;

import java.awt.AlphaComposite;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.util.Collection;

import torres.action.Effect;
import torres.entity.Avatar;
import torres.entity.Entity;
import torres.item.Item;
import torres.item.ObstacleItem;
import torres.item.TrapItem;
import torres.map.Location;
import torres.map.Map;
import torres.map.World;

@SuppressWarnings("serial")
public class TwoDAreaViewPort extends AreaViewPort {
	
	private World world;
	private int screenWidth;
	private int screenHeight;
	private BufferedImage image;
	
	public TwoDAreaViewPort() {
		
		this.world = World.getInstance();
		
		Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
		this.screenWidth = screenSize.width;
		this.screenHeight = screenSize.height;
		
		this.setPreferredSize(new Dimension(screenWidth, screenHeight));
		this.setIgnoreRepaint(true);
		
		setVisible(true);
		setFocusable(true);
	}
	
	public synchronized void paint(Graphics g) {
		
		Avatar player = world.getPlayer();
		Location pLocation = player.getLocation();
		
		Map map = World.getInstance().getCurrentMap();
		
		int offsetX = screenWidth / 2 - tilesToPixels(pLocation.getX()) - 50;
		int offsetY = screenHeight / 2 - tilesToPixels(pLocation.getY()) - 50;
		
		int firstTileX = pixelsToTiles(-offsetX);
		int lastTileX = firstTileX + pixelsToTiles(screenWidth);
		int firstTileY = pixelsToTiles(-offsetY);
		int lastTileY = firstTileY + pixelsToTiles(screenHeight);
		
		Collection<Collection<Location>> tilesToDisplay = 
				Location.radialCollection(player.getLocation(), player.getInfluenceRadius());
		g.fillRect(0, 0, screenWidth, screenHeight);
		for (int y = firstTileY; y <= lastTileY; y++) {
			for (int x = firstTileX; x <= lastTileX; x++) {
				if(x >= 0 && x < map.getWidth() && y >= 0 && y < map.getHeight()) {
					
					Location location = new Location(x, y);
					image = map.getTerrain(location).getImage();
					
					
					boolean set = false;
					A: for(Collection<Location> col : tilesToDisplay)
						if(col.contains(location)) {
							((Graphics2D) g).setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1.0f));
							set = true;
							break A;
						}
					
					if(!set)
						((Graphics2D) g).setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.3f));
					if (image != null) {
						
						g.drawImage(image, tilesToPixels(x) + offsetX, tilesToPixels(y) + offsetY, null);
					}
					
					if(map.hasDecal(location)&&set) {
						
						image = map.getDecal(location).getImage();
						
						if (image != null) {
							
							g.drawImage(image, tilesToPixels(x) + offsetX, tilesToPixels(y) + offsetY, null);
						}
					}
					
					if(map.hasItem(location)&&set) {
						
						Item item = map.getItem(location);
						
						image = item.getImage();
						
						if(image != null) {
							
							g.drawImage(image, tilesToPixels(location.getX()) + offsetX, tilesToPixels(location.getY()) + offsetY, null);
						}
					}
					if(map.hasTrap(location)&&set) {
						TrapItem t = map.getTrap(location);
						image = t.getImage();
						if(image != null && t.isVisible()) {
							g.drawImage(image, tilesToPixels(location.getX()) + offsetX, tilesToPixels(location.getY()) + offsetY, null);
						}
					}
					if(map.hasObstacle(location)&&set) {
						ObstacleItem o = map.getObstacle(location);
						image = o.getImage();
						if(image != null) {
							g.drawImage(image, tilesToPixels(location.getX()) + offsetX, tilesToPixels(location.getY()) + offsetY, null);
						}
					}
					if(map.hasEntity(location)&&set) {
						
						Entity e = map.getEntity(location);
						
						image = e.getImage();
						int eX = e.getLocation().getX();
						int eY = e.getLocation().getY();
						
						if(image != null) {
							
							if(!e.isVisible()) {
								
								if(e.equals(player)) {
									
									((Graphics2D) g).setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.3f));
								}
								else {
									
									((Graphics2D) g).setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.0f));
								}
							}
							
							g.drawImage(image, tilesToPixels(eX) + offsetX, tilesToPixels(eY) + offsetY, null);
						}
					}
					
					if(map.hasEffect(location)&&set) {
						
						Effect e = map.getEffect(location);
						image = e.getImage();
						
						if(image != null) {
							g.drawImage(image, tilesToPixels(location.getX()) + offsetX, tilesToPixels(location.getY()) + offsetY, null);
						}
					}
					
					((Graphics2D) g).setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1.0f));
				}
			}
		}
	}
	
	public void update(Graphics g) {
		
		paint(g);
	}
	
	public int pixelsToTiles(int pixel) {
		
		return pixel / 100;
	}
	
	public int tilesToPixels(int tile) {
		
		return tile * 100;
	}
}
